package com.duoduo.common.api.myinterface;


import com.duoduo.common.api.exception.lock.AddLockException;
import com.duoduo.common.api.exception.lock.ReleaseLockException;
import com.duoduo.common.api.exception.lock.UnrerentLockException;
import com.duoduo.common.api.spi.extension.SPI;
import com.duoduo.common.api.tuple.TwoTuple;

/**分布式锁操作接口
 * @author duoduo
 *
 */
@SPI
public interface LockOperator {
	
	/**尝试获取分布式锁，直接使用RedisUtil实现
	 * @param prefixName 当配置了多个集群时，可以指定使用哪个前缀的集群
     * @param appName 锁前缀
     * @param lockKey 锁的唯一标识
     * @param requestId 可以手动指定requestId，也可以手动传到threadlocal里，相当于锁重入
     * @param timeout 获取锁的超时时间，-1表示一直等待，直到获取到锁
     * @param timeOutThenExecBussiness 如果timeOut大于0，加锁超时后是返回加锁失败（timeOutThenRelease=false）还是执行业务（timeOutThenRelease=true）
     * @return 超时时间为-1：得到锁，返回true，否则一直阻塞，直到获取锁返回true；<br/>
     * 超时时间大于0：得到锁，返回true，得不到锁，等待一段时间，如果能得到，返回true，否则返回false；<br/>
     * 超时时间为0：得到锁，返回true，得不到锁，返回false
     * @throws AddLockException 加锁失败
     */
	public boolean tryGetDistributedLock(String prefixName, String appName, String lockKey, String requestId, int timeout, boolean timeOutThenExecBussiness) throws AddLockException;

	/**释放分布式锁，直接使用redisUtil
	 * @param prefixName 当配置了多个集群时，可以指定使用哪个前缀的集群
     * @param appName 锁前缀
     * @param lockKey 锁的唯一标识
     * @param release 最终是否释放锁（zk不支持）
     * @param forceRelease 不管重入了多少次，配合release=true就能直接释放redis
     * @return 如果能释放，返回true(不管是中途释放还是全部释放都是true)；没有锁，或者不是自己加的锁返回false
     * @throws ReleaseLockException 释放锁失败
     * @throws UnrerentLockException 停止续租失败
     */
    public boolean releaseDistributedLock(String prefixName, String appName, String lockKey, Boolean release, Boolean forceRelease) throws ReleaseLockException, UnrerentLockException;

    /**注意：zk不支持
     * 获取threadlocal里的requestId和count，已经不建议使用，直接返回<null, null>
     * @return
     */
    @Deprecated
    public TwoTuple<String, Integer> getLockRequestIdAndCount();
    
    /**注意：zk不支持
     * 获取threadlocal里的requestId和count，获取完之后就清除threadlocal，因为这个操作意味着要变换线程了
     * @return
     */
    public TwoTuple<String, Integer> getLockRequestIdAndCount(String lockKey);

}
